#include	"lp_global_vars.h"

proposer_msg *m;
char proposerID_char[STRING_SIZE];
char name_g[STRING_SIZE];
FILE *f_g;

//------------------------------------------------------------------------------
double getMiliseconds() {
	struct timeval mtv;
	gettimeofday(&mtv, NULL);
	double msec = 1000 * mtv.tv_sec + mtv.tv_usec / (double) 1000;
	return msec;
}
//------------------------------------------------------------------------------
void p_initialize() {
	m = (proposer_msg*) malloc(sizeof(proposer_msg));
	sprintf(proposerID_char, "%d", proposerID);
}
//------------------------------------------------------------------------------
int pickID() {
	//	int MSG_ID;
	//	int temp;
	//	char stringTemp[STRING_SIZE];
	digit++;
	//	temp = digit * 10;
	//	sprintf(stringTemp, "%d", temp);
	//	MSG_ID = atoi(strcat(stringTemp, proposerID_char));
	//	return MSG_ID;
	return digit;

}
//------------------------------------------------------------------------------
void send_msg(int to_propose) {
	unsigned int slen = sizeof(server_addr);
	p_msgs[to_propose % INTERNAL_BUFFER_SIZE].microseconds = getMiliseconds();

	int status = sendto(get_config_info()->proposer_to_multicaster_sid, &p_msgs[to_propose % INTERNAL_BUFFER_SIZE], sizeof(proposer_msg), 0, (struct sockaddr*) &server_addr, slen);
	assert(status == sizeof(proposer_msg));
	lp_interval_performance->interval_bytes_sent += status;
}
//------------------------------------------------------------------------------
void generate_msg(int sd, short event, void * arg) {

	UNUSED_ARG(sd);
	UNUSED_ARG(event);
	UNUSED_ARG(arg);
	//	learner_deliver();
	int counter = 0;
	struct timeval current_proposal_time;
	gettimeofday(&current_proposal_time, NULL);
	double msec = measure_time_difference(current_proposal_time, last_proposal_time);

	if (msec > 30) {
		traveres_for_gaps();
		counter = check_for_missed_packets();
	}
	lp_interval_performance->interval_num_entrance++;

	while (counter < SUBMIT_PER_WAKE && lp_interval_performance->next_to_propose_slot_number < INTERNAL_BUFFER_SIZE + lp_interval_performance->last_delivered) {
		int index = lp_interval_performance->next_to_propose_slot_number % INTERNAL_BUFFER_SIZE;
		p_msgs[index].msg_id = pickID();
		p_msgs[index].node_id = proposerID;
		p_msgs[index].location_in_proposer = lp_interval_performance->next_to_propose_slot_number;
		p_msgs[index].delivered = 'n';

		send_msg(lp_interval_performance->next_to_propose_slot_number);
		counter++;

		lp_interval_performance->interval_num_packets_sent++;
		lp_interval_performance->next_to_propose_slot_number++;
	}
	evtimer_add(timeoutEv2, &tv2);
}
//------------------------------------------------------------------------------
int check_for_missed_packets() {
	int counter = 0;
	int missing = lp_interval_performance->last_gapless_delivered;
	int limit = lp_interval_performance->last_delivered;

	if (lp_interval_performance->next_to_propose_slot_number - lp_interval_performance->last_delivered == INTERNAL_BUFFER_SIZE) {
		limit = lp_interval_performance->next_to_propose_slot_number;
	}

	if (missing == -1)
		missing = 0;

	while (missing < limit) {
		if (counter < SUBMIT_PER_WAKE) {
			send_msg(missing);
			missing++;
			lp_interval_performance->interval_repeated_requets++;
			counter++;
		} else
			break;
	}

	return counter;
}
